package com.mine.frame.mylandemo.ui.jiecang

import android.annotation.SuppressLint
import android.app.Service
import android.content.ComponentName
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.text.Editable
import android.util.Log
import android.view.MotionEvent
import android.view.View
import com.blankj.utilcode.util.ClickUtils
import com.blankj.utilcode.util.KeyboardUtils
import com.blankj.utilcode.util.ServiceUtils
import com.blankj.utilcode.util.SnackbarUtils
import com.mine.frame.common.base.BaseActivity
import com.mine.frame.mylandemo.R
import com.mine.frame.mylandemo.adapter.forick.Panel3In1Adapter
import com.mine.frame.mylandemo.entity.forick.ControlBean
import com.mine.frame.mylandemo.mvp.iview.IDreamCurtain
import com.mine.frame.mylandemo.mvp.iview.ITranslationDesk
import com.mine.frame.mylandemo.mvp.presenter.DreamCurtainPresenter
import com.mine.frame.mylandemo.mvp.presenter.TranslationDeskPresenter
import com.mine.frame.mylandemo.ui.dialog.LoadingDialog
import com.swallowsonny.convertextlibrary.toHexString
import com.third.device.mg.serialport.MGSerialPort
import com.third.device.mg.serialport.listener.MGNettyConnectListener
import com.third.device.mg.serialport.service.MGSocketService
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.android.synthetic.main.atv_forick_panel_3in1.*
import kotlinx.android.synthetic.main.atv_forick_panel_3in1.mRecycler
import kotlinx.android.synthetic.main.atv_jiecang_translation.*
import kotlinx.android.synthetic.main.layout_connect.*
import java.util.concurrent.TimeUnit
import kotlin.math.abs

/**
 * @Date 2022/2/12
 * Description:
 * 波特率：9600
 */
@SuppressLint("SetTextI18n")
class TranslationDeskAtv : BaseActivity<ITranslationDesk, TranslationDeskPresenter>(),
    ITranslationDesk,
    MGNettyConnectListener {
    /*当前连接的IP地址 和 端口号*/
    private var ipStr = ""
    private var port = 61233

    companion object {
        private const val ERROR_RANGE = 2 //误差范围2mm以上
    }

    private var maxHeight = 0
    private var minHeight = 0
    private var isGetDevScopeRange = false //是否获取设备行程范围
    private var isSentUp = false //是否发送上升
    private var isSentDown = false //是否发送下降
    private var initHeight = false

    private val mAdapter by lazy { Panel3In1Adapter() }

    private var sentDisposable: Disposable? = null

    private val loading by lazy { LoadingDialog(this) }

    override fun initLayoutId(): Int = R.layout.atv_jiecang_translation

    override fun initPresenter(): TranslationDeskPresenter = TranslationDeskPresenter(this)

    private val serviceConnect: ServiceConnection by lazy {
        object : ServiceConnection {
            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                SnackbarUtils.with(tvInfo).setMessage("正在连接服务器...").showSuccess()
                MGSocketService.get().setListener(this@TranslationDeskAtv)
            }

            override fun onServiceDisconnected(name: ComponentName?) {
            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun initLayoutAfter(savedInstanceState: Bundle?) {
        val oldCommand = intent?.getBooleanExtra("oldCommand" ,true)?:true
        tvModel.text = if (oldCommand) "指令模式:旧指令(无适配器)" else "指令模式:新指令(有适配器)"
        ipStr = intent?.getStringExtra("sel-ip").toString()
        edtIP.text = Editable.Factory.getInstance().newEditable(ipStr)
        connectAndDisconnect()
        initRecycler()
        mPresenter.createControlData(oldCommand)


        if (!oldCommand){
            mRadioGroup.visibility = View.GONE
            tvHint.visibility = View.GONE
            ivLeft.visibility = View.GONE
            ivRight.visibility = View.GONE
            btnQueryStroke.visibility = View.GONE
        }

        //点击获取行程信息
        ClickUtils.applySingleDebouncing(btnQueryStroke) {
            val listCommand = arrayListOf<ByteArray>()
            //行程范围
            val routeScope = MGSerialPort.instance.getJieCang().translationDesk().routeScope()
            //限位状态
            val queryLimitState =
                MGSerialPort.instance.getJieCang().translationDesk().queryLimitState()
            listCommand.add(routeScope)
            listCommand.add(queryLimitState)
            val listEmitter = Observable.fromIterable(listCommand)
            val timeEmitter = Observable.interval(300, TimeUnit.MILLISECONDS)
            Observable.zip(listEmitter, timeEmitter) { command, time ->
                if (command.contentEquals(routeScope)){
                    isGetDevScopeRange = true
                }else if (command.contentEquals(queryLimitState)){
                    initHeight = true
                }
                MGSocketService.get().write(ipStr, port, command)
            }.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe {
                    if (!loading.isShowing){
                        loading.show()
                    }
                }
                .doOnComplete {
                    loading.dismiss()
                }
                .subscribe()
        }
        val upCommand = MGSerialPort.instance.getJieCang().translationDesk().up()
        val downCommand = MGSerialPort.instance.getJieCang().translationDesk().down()
        ivLeft.setOnLongClickListener {
            continuousSentCommand(downCommand)
            false
        }
        ivRight.setOnLongClickListener {
            continuousSentCommand(upCommand)
            false
        }
        ivLeft.setOnTouchListener { _, event ->
            if (event.action == MotionEvent.ACTION_UP){
                destroySentDisposable()
            }
            false
        }
        ivRight.setOnTouchListener { _, event ->
            if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL){
                destroySentDisposable()
            }
            false
        }
    }


    /**
     * 连接和取消连接
     */
    private fun connectAndDisconnect() {
        ClickUtils.applySingleDebouncing(arrayOf(btnConnect, btnDisconnect)) {
            when (it.id) {
                R.id.btnConnect -> {
                    KeyboardUtils.hideSoftInput(this)
                    if (edtIP.text.isNullOrEmpty()) {
                        SnackbarUtils.with(edtIP).setMessage("请输入IP地址").showWarning()
                        return@applySingleDebouncing
                    } else {
                        ipStr = edtIP.text.toString()
                    }


                    if (edtPort.text.isNullOrEmpty()) {
                        SnackbarUtils.with(edtIP).setMessage("请输入端口号").showWarning()
                        return@applySingleDebouncing
                    } else {
                        port = edtPort.text.toString().toInt()
                        if (port < 1 || port > 65535) {
                            SnackbarUtils.with(edtIP).setMessage("端口号异常(1,65535)").showWarning()
                            return@applySingleDebouncing
                        }
                    }
                    if (ipStr.isEmpty()) {
                        SnackbarUtils.with(edtIP).setMessage("IP地址异常").showError()
                        return@applySingleDebouncing
                    }

                    initSocket()
                }
                R.id.btnDisconnect -> {
                    MGSocketService.get().disconnect(ipStr, port)
                }
            }
        }

    }


    override fun onStart() {
        super.onStart()
        if (!MGSocketService.get().isBind) {
            ServiceUtils.bindService(
                MGSocketService::class.java,
                serviceConnect,
                Service.BIND_AUTO_CREATE
            )
        }
    }


    /**
     * 创建Socket连接
     */
    private fun initSocket() {
        MGSocketService.get().connectNetty(ipStr, port)
    }


    /**
     * 更新指示器
     */
    private fun updateIndicator(connect: Boolean) {
        val resId = if (connect) {
            R.drawable.blue_circle
        } else {
            R.drawable.red_circle
        }
        viewIndicator.setBackgroundResource(resId)
    }

    override fun onDestroy() {
        if (MGSocketService.get().isBind) {
            ServiceUtils.unbindService(serviceConnect)
        }
        destroySentDisposable()
        super.onDestroy()
    }

    private fun initRecycler() {
        mRecycler.adapter = mAdapter
        mAdapter.setOnItemClickListener { _, _, position ->
            val controlBean = mAdapter.data[position]
            this.initHeight = false
            mPresenter.exitInitHeightMode()
            if (!controlBean.isHeader) {
                controlBean.command?.let {
                    //MGSocketService.get().write(ipStr ,port ,it)
                    //只有上升 和 下降 分电动和连续模式
                    if ("上升(连动模式下会一直发指令)" == controlBean.controlName || "下降(连动模式下会一直发指令)" == controlBean.controlName) {
                        if (mRadioGroup.checkedRadioButtonId == rBtnContinuous.id) {//连动模式
                            if ("上升(连动模式下会一直发指令)" == controlBean.controlName) {
                                isSentUp = true
                            } else if ("下降(连动模式下会一直发指令)" == controlBean.controlName) {
                                isSentDown = true
                            }
                            continuousSentCommand(it)
                        } else {//点动模式
                            MGSocketService.get().write(ipStr, port, it)
                        }
                    } else if ("行程范围" == controlBean.controlName) {
                        isGetDevScopeRange = true
                        MGSocketService.get().write(ipStr, port, it)
                    } else if ("停止" == controlBean.controlName) {
                        destroySentDisposable()
                        MGSocketService.get().write(ipStr, port, it)
                    } else if ("查询限位状态" == controlBean.controlName || "查询上限位情况" == controlBean.controlName || "查询下限位情况" == controlBean.controlName) {
                        this.initHeight = true
                        MGSocketService.get().write(ipStr, port, it)
                    } else {
                        MGSocketService.get().write(ipStr, port, it)
                    }
                } ?: let {
                    SnackbarUtils.with(btnConnect).setMessage("指令未空").showWarning(true)
                }
            }
        }
    }


    /**
     * 连续发送指令
     */
    private fun continuousSentCommand(command: ByteArray) {
        destroySentDisposable()
        sentDisposable = Observable.interval(100, TimeUnit.MILLISECONDS)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext {
                MGSocketService.get().write(ipStr, port, command)
            }
            .doOnComplete {
                val stop = MGSerialPort.instance.getJieCang().translationDesk().stop()
                MGSocketService.get().write(ipStr, port, stop)
            }
            .subscribe()
    }


    private fun destroySentDisposable() {
        sentDisposable?.let {
            if (!it.isDisposed) {
                it.dispose()
                isSentDown = false
                isSentUp = false
            }
        }
    }

    override fun connectBack(ip: String, port: Int) {
        updateIndicator(true)
    }

    override fun disconnectBack(ip: String, port: Int) {
        updateIndicator(false)
    }


    override fun readBack(ip: String, port: Int, result: ByteArray) {
        SnackbarUtils.with(btnConnect).setMessage("收到消息").showSuccess(true)
        tvInfo.text = "接收:${result.toHexString(true)}"

        when {
            isGetDevScopeRange -> {
                mPresenter.parseScope(result)
            }
            initHeight -> {
                mPresenter.parseLimitHeight(result)
            }
            else -> {
                mPresenter.parseHeight(result)
            }
        }
    }

    override fun writeBack(ip: String, port: Int, successful: Boolean, data: ByteArray) {
        if (successful) {
            SnackbarUtils.with(btnConnect).setMessage("发送成功").showSuccess(true)
        } else {
            SnackbarUtils.with(btnConnect).setMessage("发送失败").showError(true)
        }
    }

    override fun errorBack(ip: String, port: Int, error: Throwable) {
        error.message?.let {
            showErr(it)
        }
    }

    override fun initControlList(data: MutableList<ControlBean>) {
        mAdapter.setList(data)
    }

    override fun deviceHeightMM(height: Int) {
        Log.e("height:", "$height mm")
        tvRead.text = "max:${maxHeight / 10f}cm  min:${minHeight / 10f}cm  当前高度: ${height / 10f}cm"

        if (isSentDown && height <= minHeight) {
            Log.e("停止(下限位)==>>", "height:$height   min:$minHeight")
            destroySentDisposable()
        }

        if (isSentUp && height >= maxHeight) {
            Log.e("停止(上限位)==>>", "height:$height   min:$maxHeight")
            destroySentDisposable()
        }
    }

    override fun deviceHeightScopeMM(heightH: Int, heightL: Int) {
        isGetDevScopeRange = false
        maxHeight = heightH
        minHeight = heightL
        SnackbarUtils.with(btnConnect).setMessage("行程范围已经确认").showSuccess(true)
    }

    override fun setDeviceHeightMode(getHeightMode: Boolean) {
        this.initHeight = getHeightMode
    }

    override fun isDeviceHeightMode(): Boolean = this.initHeight
    override fun noneSettingLimit() {

    }

    override fun limitUpLimit(height: Int) {
        maxHeight = height
    }

    override fun limitDownLimit(height: Int) {
        minHeight = height
    }
}